﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using Microsoft.Win32;

namespace SkypeTranslater
{
	[RunInstaller(true)]
	public partial class SkypeTranslaterInstaller : System.Configuration.Install.Installer
	{
		public SkypeTranslaterInstaller()
		{
			InitializeComponent();
		}

		protected override void OnBeforeInstall(IDictionary savedState)
		{
			base.OnBeforeInstall(savedState);
			Context.LogMessage("BeforeInstall");
			Context.LogMessage("Begin execution of process kill");

			KillProcess();
		}

		public override void Install(IDictionary stateSaver)
		{
			base.Install(stateSaver);
		}

		protected override void OnAfterInstall(IDictionary savedState)
		{
			base.OnAfterInstall(savedState);
			Context.LogMessage("[AfterInstall]");

			bool IsExist1 = Context.IsParameterTrue("isEx1");
			Context.LogMessage("IsExist1: " + IsExist1.ToString());

			bool blendExist = Context.IsParameterTrue("blend");
			Context.LogMessage("blendExist: " + blendExist.ToString());

			if (IsExist1)
			{
				Context.LogMessage("Skype4COM.dll exists");
			}

			if (this.Context != null && this.Context.Parameters.ContainsKey("td"))
			{
				string currentUser = string.Format(@"{0}\{1}", Environment.UserDomainName, Environment.UserName);
				Context.LogMessage("Curent user: " + currentUser);

				string folder = Context.Parameters["td"].Remove(Context.Parameters["td"].Length - 1);
				Context.LogMessage("Setup folder: " + folder);
				try
				{
					foreach (string subFolder in System.IO.Directory.EnumerateDirectories(folder))
					{
						try
						{
							SetDirectoryRights(subFolder, currentUser);
						}
						catch (System.UnauthorizedAccessException ex) { Context.LogMessage(ex.Message); }
						catch (System.IO.IOException ex) { Context.LogMessage(ex.Message); }
					}

					SetDirectoryRights(folder, currentUser);
				}
				catch (System.UnauthorizedAccessException ex) { Context.LogMessage(ex.Message); }
				catch (System.IO.IOException ex) { Context.LogMessage(ex.Message); }

				Context.LogMessage("Work with registry");

				try
				{
					string regKeyName = string.Format("{0}{1}", Context.Parameters["pn"], Context.Parameters["pv"]);
					using (RegistryKey key = Registry.CurrentUser.OpenSubKey(string.Format(@"Software\{0}", regKeyName), RegistryKeyPermissionCheck.ReadWriteSubTree))
					{
						if (key != null && key.ValueCount == 1)
						{
							key.SetValue("ProgramPath", folder);
							Context.LogMessage("Program path set successfully");
							Context.LogMessage(folder);
							key.Flush();
							key.Close();
						}
					}
				}
				catch (System.UnauthorizedAccessException ex) { Context.LogMessage(ex.Message); }
				catch (System.Security.SecurityException ex) { Context.LogMessage(ex.Message); }
				catch (System.IO.IOException ex) { Context.LogMessage(ex.Message); }

				Context.LogMessage("Begin of shortcut creation");
				try
				{
					System.Diagnostics.Process scriptProc = new System.Diagnostics.Process();
					scriptProc.StartInfo.FileName = System.IO.Path.Combine(folder, "CreateShortcut.vbs");
					scriptProc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; //prevent console window from popping up
					scriptProc.Start();
					scriptProc.WaitForExit();
					scriptProc.Close();
					Context.LogMessage("Enf of shortcut creation");
				}
				catch (Exception ex) { Context.LogMessage(ex.Message); }
				Context.LogMessage("End of shortcut creation");

				Context.LogMessage("Begin of copy log4net.dll");
				var dirInfo = new System.IO.DirectoryInfo(folder);
				if (dirInfo.Exists && dirInfo.EnumerateFiles("log4*.dll").Any())
				{
					Context.LogMessage("Begin file copy");
					try
					{
						System.IO.File.Copy(dirInfo.EnumerateFiles("log4*.dll").First().FullName, System.IO.Path.Combine(folder, @"Service\log4net.dll"), true);
						Context.LogMessage("File log4net.dll copied successfully");
					}
					catch (Exception e) { Context.LogMessage(e.Message); }

				}
				Context.LogMessage("End of copy log4net.dll");
			}
		}

		public override void Uninstall(IDictionary savedState)
		{
			base.Uninstall(savedState);
			Context.LogMessage("Uninstall");

			Context.LogMessage("Begin of process kill");
			KillProcess();

			if (this.Context != null && this.Context.Parameters.ContainsKey("td"))
			{
				string folder = Context.Parameters["td"].Remove(Context.Parameters["td"].Length - 1);
				Context.LogMessage(folder);

				try
				{
					string keyName = string.Format("{0}{1}", Context.Parameters["pn"], Context.Parameters["pv"]);
					using (RegistryKey key = Registry.CurrentUser.OpenSubKey(string.Format(@"Software\{0}", keyName), RegistryKeyPermissionCheck.ReadWriteSubTree))
					{
						if (key != null && key.ValueCount == 1)
						{
							key.DeleteValue("ProgramPath", true);
							key.Flush();
							key.Close();
						}
					}
				}
				catch (System.UnauthorizedAccessException ex) { Context.LogMessage(ex.Message); }
				catch (System.Security.SecurityException ex) { Context.LogMessage(ex.Message); }
				catch (System.IO.IOException ex) { Context.LogMessage(ex.Message); }
			}

			string StartUserMenu = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
														@"\Microsoft\Windows\Start Menu\SkypeTranslater\");

			if (System.IO.Directory.Exists(StartUserMenu))
			{
				foreach (string file in System.IO.Directory.EnumerateFiles(StartUserMenu))
				{
					try
					{
						System.IO.File.Delete(file);
					}
					catch (System.IO.IOException ex) { Context.LogMessage(ex.Message); }
					catch (System.UnauthorizedAccessException ex) { Context.LogMessage(ex.Message); }
				}
			}

			if (System.IO.Directory.Exists(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Desktop")))
			{
				if (System.IO.File.Exists(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @"Desktop\SkypeTranslator.lnk")))
				{
					try
					{
						System.IO.File.Delete(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @"Desktop\SkypeTranslator.lnk"));
					}
					catch (System.IO.IOException ex) { Context.LogMessage(ex.Message); }
					catch (System.UnauthorizedAccessException ex) { Context.LogMessage(ex.Message); }
				}
			}

		}

		public override void Rollback(IDictionary savedState)
		{
			base.Rollback(savedState);
			Context.LogMessage("Rollback");

			if (this.Context != null && this.Context.Parameters.ContainsKey("assemblypath") && Context.Parameters["action"].Contains("uninstall"))
			{
				string folder = System.IO.Path.GetDirectoryName(Context.Parameters["assemblypath"]);
				if (System.IO.Directory.Exists(folder))
				{
					try
					{
						System.IO.Directory.Delete(folder, true);
					}
					catch (System.IO.IOException ex) { Context.LogMessage(ex.Message); }
					catch (System.UnauthorizedAccessException ex) { Context.LogMessage(ex.Message); }
				}

				string StartUserMenu = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
														@"\Microsoft\Windows\Start Menu\SkypeTranslater\");


				if (System.IO.Directory.Exists(StartUserMenu))
				{
					foreach (string file in System.IO.Directory.EnumerateFiles(StartUserMenu))
					{
						try
						{
							System.IO.File.Delete(file);
						}
						catch (System.IO.IOException ex) { Context.LogMessage(ex.Message); }
						catch (System.UnauthorizedAccessException ex) { Context.LogMessage(ex.Message); }
					}
				}

				if (System.IO.Directory.Exists(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Desktop")))
				{
					if (System.IO.File.Exists(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @"Desktop\SkypeTranslator.lnk")))
					{
						try
						{
							System.IO.File.Delete(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @"Desktop\SkypeTranslator.lnk"));
						}
						catch (System.IO.IOException ex) { Context.LogMessage(ex.Message); }
						catch (System.UnauthorizedAccessException ex) { Context.LogMessage(ex.Message); }
					}
				}
			}
		}

		#region Helper methods

		private void RunProcess(string exePath, string parameters)
		{
			System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo();
			info.FileName = exePath;
			info.Arguments = parameters;
			info.CreateNoWindow = false;
			info.UseShellExecute = true;
			info.RedirectStandardError = true;
			info.RedirectStandardOutput = true;
			info.WorkingDirectory = System.IO.Path.GetDirectoryName(exePath);

			var process = System.Diagnostics.Process.Start(info);
			//process.WaitForExit();
		}

		private void RunProcess2(string exePath, string parameters)
		{
			System.Diagnostics.Process process = null;
			try
			{
				System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo();
				info.FileName = exePath;
				info.Arguments = parameters;
				info.CreateNoWindow = false;
				info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
				info.UseShellExecute = false;
				info.RedirectStandardError = true;
				info.RedirectStandardOutput = true;
				info.RedirectStandardInput = true;
				info.WorkingDirectory = System.IO.Path.GetDirectoryName(exePath);

				process = new System.Diagnostics.Process();
				process.StartInfo = info;
				process.EnableRaisingEvents = true;

				process.Start();
				process.WaitForExit();
			}
			catch (Exception ex) { throw; }
			finally { process.Close(); }
		}

		private void SetDirectoryRights(string folder, string user)
		{
			System.IO.DirectoryInfo dirInfo = new System.IO.DirectoryInfo(folder);
			if (!dirInfo.Exists)
				return;

			System.Security.AccessControl.DirectorySecurity dirSec = dirInfo.GetAccessControl();

			var acl = new System.Security.AccessControl.FileSystemAccessRule(user, System.Security.AccessControl.FileSystemRights.FullControl, System.Security.AccessControl.AccessControlType.Allow);
			dirSec.AddAccessRule(acl);
			dirInfo.SetAccessControl(dirSec);
		}

		private void KillProcess()
		{
			foreach (System.Diagnostics.Process p in System.Diagnostics.Process.GetProcessesByName("SkypeTranslator"))
			{
				try
				{
					foreach (System.Diagnostics.ProcessModule module in p.Modules)
					{
						if (module.FileName.Equals("SkypeTranslator.exe"))
						{
							p.Kill();
							p.WaitForExit();
						} // possibly with a timeout
					}
				}
				catch (Win32Exception ex)
				{
					Context.LogMessage(ex.Message);
				}
				catch (InvalidOperationException ex)
				{
					Context.LogMessage(ex.Message);
				}
			}
		}

		#endregion
	}
}
